#include "Qt3DPicker.h"

#include "D2To3Handler.h"
#include "CmdManager.h"
#include "Scene.h"
#include "SendPointHandlerBase.h"
#include "SelectHandler3D.h"
#include "OSGNodeMask.h"
#include "Operation/OpAdd.h"
#include "Ent.h"
#include "Pline2D.h"
#include "QtOSGWidget.h"

D2To3Handler::D2To3Handler()
{
}

D2To3Handler::~D2To3Handler()
{
}

void D2To3Handler::input(const QVariant& data, const QString& rawInput, CommandSource cs)
{
	auto scene = getScene();
	auto widget3D = getWidget();
	auto sph = getSendPointHandler();
	auto selector = qobject_cast<SelectHandler3D*>(getSelectHandler());
	if (data.type() == QVariant::Bool)
	{
		bool esc = !data.toBool();
		if (esc)
		{
			if (!m_ent3ds.empty())
			{
				widget3D->pauseRenderThread();
				for (auto ent3d : m_ent3ds)
				{
					scene->removeChild(ent3d);
				}
				widget3D->resumeRenderThread();
			}
			selector->clearSelection();
			clearInput();
			emit finished();
			return;
		}
	}

	if (status() == 0)
	{
		if (selector)
		{
			selector->clearSelection();
			selector->beginSelect(D2CurveMask);
			prompt(1, tr("选择二维对象: "));
		}
		else
		{
			emit finished();
		}
		return;
	}

	if (status() == 1)
	{
		if (selector && selector->done())
		{
			auto selections = selector->selectionSet();
			if (selections.size() > 0)
			{
				auto selection = *selections.begin();
				std::shared_ptr<Ent> ent = std::dynamic_pointer_cast<Ent>(selection);
				auto parent = ent->getParent();
				UCS* ucs = dynamic_cast<UCS*>(parent);
				if (ucs)
				{
					m_ucs = ucs;
				}
				else
				{
					remark(tr("请选择二维图形"));
					emit finished();
					return;
				}

				for (auto selection : selections)
				{
					std::shared_ptr<Ent2D> ent2d = std::dynamic_pointer_cast<Ent2D>(selection);
					auto parent = ent2d->getParent();
					UCS* ucs = dynamic_cast<UCS*>(parent);
					if (ucs != m_ucs)
						continue;
					m_origins.insert(ent2d);
				}

				if (sph)
				{
					sph->setPointMask(CS_LBTNDOWN | CS_MOUSEMOVE);
				}
				enableMouseHandler(MouseHandlerID::PointSender);
				prompt(2, tr("输入起点或距离<0>:"));
			}
			else
			{
				emit finished();
			}
		}
		return;
	}

	if(status() == 2)
	{
		if (data.type() == QVariant::Vector3D)
		{
			if (cs == CS_MOUSEMOVE)
				return;
			auto pt = data.value<QVector3D>();
			m_start = m_end = { pt.x(),pt.y(),pt.z() };
			show3DRubberLine(true);
			set3DRubberLineP1(m_start);
			set3DRubberLineP2(m_end);
			prompt(3, tr("输入终点:"));
		}
		else if (data.type() == QVariant::Double || data.type() == QVariant::Bool)
		{
			double offset;
			if (data.type() == QVariant::Bool)
				offset = 0;
			else
				offset = data.value<double>();
			to3ds(m_origins, m_ent3ds);
			for (auto ent3d : m_ent3ds)
			{
				std::shared_ptr<Ent> ent = std::static_pointer_cast<Ent>(ent3d);
				osg::Vec3d offsetVec = m_ucs->zAxis() * offset;
				ent->move(offsetVec);
			}
			selector->clearSelection();
			auto undoStack = scene->undoStack();
			undoStack->push(new OpAdd(m_ent3ds));
			emit finished();
		}
		return;
	}

	if (status() == 3)
	{
		if (data.type() == QVariant::Vector3D)
		{
			auto pt = data.value<QVector3D>();
			osg::Vec3d worldpt = { pt.x(),pt.y(),pt.z() };
			auto thisoffset = worldpt - m_end;
			m_end = worldpt;
			double offset = thisoffset * m_ucs->zAxis();
			if (m_ent3ds.empty())
			{
				to3ds(m_origins, m_ent3ds);
				widget3D->pauseRenderThread();
				for (auto ent3d : m_ent3ds)
				{
					scene->addChild(ent3d);
				}
				widget3D->resumeRenderThread();
			}
			for (auto ent3d : m_ent3ds)
			{
				std::shared_ptr<Ent> ent = std::static_pointer_cast<Ent>(ent3d);
				osg::Vec3d offsetVec = m_ucs->zAxis() * offset;
				ent->move(offsetVec);
			}
			if (cs == CS_MOUSEMOVE)
			{
				set3DRubberLineP2(m_end);
			}		
			else
			{
				widget3D->pauseRenderThread();
				for (auto ent3d : m_ent3ds)
				{
					scene->removeChild(ent3d);
				}
				widget3D->resumeRenderThread();
				show3DRubberLine(false);
				selector->clearSelection();
				auto undoStack = scene->undoStack();
				undoStack->push(new OpAdd(m_ent3ds));
				emit finished();
			}
		}
		return;
	}

}

void D2To3Handler::to3ds(std::set<std::shared_ptr<Ent2D>>& origins, std::set<std::shared_ptr<INode>>& children)
{
	for (auto origin : origins)
	{	
		auto ent2d = std::dynamic_pointer_cast<Ent2DCurve>(origin);
		auto ent3ds = ent2d->to3d();
		for (auto ent3d : ent3ds)
		{
			ent3d->setColor(getCurrentColor());
			children.insert(ent3d);
		}		
	}
}
